import os, sys
from typing import Optional, List, Literal
from dotenv import load_dotenv
from functools import lru_cache
from pathlib import Path

from pydantic_settings import BaseSettings
from pydantic import model_validator

from .mysql_config import get_mysql_config
from .sqlite_config import get_sqlite_config

load_dotenv()

class Settings(BaseSettings):
    
    class Config:
        env_file = ".env"
        # env_file = f".env.{os.getenv('ENV', 'dev')}"
    
    PROJECT_ROOT: str = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
    BASE_DIR: str = os.path.abspath(os.path.join(PROJECT_ROOT, os.pardir))
        
    VERSION: str
    APP_TITLE: str
    PROJECT_NAME: str
    APP_DESCRIPTION: str
    
    API_V1_STR: str = '/api/v1'
    DOCS_URL: str | None = f'{API_V1_STR}/docs'
    REDOCS_URL: str | None = f'{API_V1_STR}/redocs'
    OPENAPI_URL: str | None = f'{API_V1_STR}/openapi'

    CORS_ORIGINS: List = ["*"]
    CORS_ALLOW_CREDENTIALS: bool = True
    CORS_ALLOW_METHODS: List = ["*"]
    CORS_ALLOW_HEADERS: List = ["*"]
    
    ENV: Literal['prd', 'dev', 'test']

    DEBUG: bool
    # 重启
    RELOAD: bool
    
    BACKEND_HOST: str
    BACKEND_PORT: int   
    WORKERS: int
    
    '''
    redis 配置
    '''
    ENABLE_REDIS: bool
    # 带密码 "redis://:{passwd}@localhost:6379"
    REDIS_URL: str
    
    # 启用中间件
    MIDDLEWARE_ACCESS: bool
    MIDDLEWARE_CORS: bool
    
    '''
    minio 配置
    '''
    MINIO_URL: str
    MINIO_ACCESSKEY: str
    MINIO_SECRETKEY: str
    MINIO_API: str
    MINIO_PATH: str
    MINIO_BUCKETNAME: str
    MINIO_SECURE: bool
    
    '''
    数据库配置，添加默认值防止 TORTOISE_ORM 报错
    .env 文件的值会覆盖这里的值
    '''
    ENABLE_DB: bool
    # 数据库类型
    DB_TYPE: Literal['sqlite', 'mysql', 'postgresql']
    DB_HOST: str
    DB_PORT: int
    DB_USER: str
    DB_PASSWD: str
    DB_DATABASE: str
    DB_CHARSET: str
    DB_POOL_SIZE: int
    
    DB_PATH: str
    
    TORTOISE_ORM: Optional[dict] = None
    
    @model_validator(mode='before')
    def validate_fields(cls, values):
        if 'DB_PATH' not in values:
            values['DB_PATH'] = (Path(__file__).resolve().parent.parent.parent / "data").as_posix()
        values['TORTOISE_ORM'] = get_db_config(
            db_type=values['DB_TYPE'],
            db_host=values['DB_HOST'],
            db_port=values['DB_PORT'],
            db_user=values['DB_USER'],
            db_passwd=values['DB_PASSWD'],
            db_database=values['DB_DATABASE'],
            db_charset=values['DB_CHARSET'],
            db_pool_size=values['DB_POOL_SIZE'],
            db_path=values['DB_PATH']
        )
        return values
        
    '''
    接口频率限制
    '''
    ENABLE_LIMITER: bool = False
    REQUEST_LIMITER_REDIS_PREFIX: str = 'fm:limiter'
    
    DATETIME_FORMAT: str = "%Y-%m-%d %H:%M:%S"
    
    MAX_CONCURRENT_TASKS: int = 10

    # 文件限制大小
    MAX_FILE: int  = 500 * 1024 * 1024
    # 文件保存路径
    PATH_SAVE_FILE: str = BASE_DIR + "/file/"
    # 文件分块读取大小
    CHUNK_SIZE: int = 1024
    
    # Http 请求超时时间
    REQUEST_TIME_OUT: int = 30
    
    FORMAT_LOG: bool = True
    # 日志目录
    LOG_ERROR_DIR: str = os.path.join(BASE_DIR, "log", "error", "error_{time:YYYY-MM-DD}.log")
    LOG_INFO_DIR: str = os.path.join(BASE_DIR, "log", "info", "info_{time:YYYY-MM-DD}.log")

def get_db_config(
    db_type: str,
    db_host: str,
    db_port: int,
    db_user: str,
    db_passwd: str,
    db_database: str,
    db_charset: str,
    db_pool_size: int,
    db_path: Optional[str] = None
) -> dict:
    if db_type == 'mysql':
        return get_mysql_config(
            db_host=db_host,
            db_port=db_port,
            db_user=db_user,
            db_passwd=db_passwd,
            db_database=db_database,
            db_charset=db_charset,
            db_pool_size=db_pool_size
        )
    elif db_type == 'sqlite':
        return get_sqlite_config(
            sqlite_path=db_path,
            pool_size=db_pool_size
        )
    else:
        return None

@lru_cache
def get_settings():
    """读取配置优化写法"""
    return Settings()

settings = get_settings()

TORTOISE_ORM = settings.TORTOISE_ORM
